/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <unistd.h>
#include "pag_napi_pagPlayer.h"
#include "hilog/log.h"
#include "pag/pag.h"
#include <bits/alltypes.h>
#include "pag_napi_pagFile.h"
#include <iostream>
#include <fstream>
#include <filesystem>
#include "PagSurface.h"
#include <native_vsync/native_vsync.h>
#include <unistd.h>
#include <iostream>
using namespace pag;

namespace NativeXComponentSample {
const int32_t STR_DEFAULT_SIZE = 2048;
const int32_t INDEX_0 = 0;
const int32_t INDEX_1 = 1;
const int32_t INDEX_2 = 2;
const int32_t INDEX_3 = 3;
const int32_t PARAM_COUNT_1 = 1;
const int32_t PARAM_COUNT_2 = 2;
const int32_t PARAM_COUNT_3 = 3;
const int32_t PARAM_COUNT_4 = 4;

const unsigned int LOG_PRINT_DOMAIN = 0XFF00;
napi_ref PAGPlayer::sJSPlayerConstructor_ = nullptr;
std::unordered_map<std::string, PAGPlayer *> PAGPlayer::pagPlayerNapi_;

PAGPlayer::~PAGPlayer()
{
    if (mRef != nullptr) {
        napi_delete_reference(mEnv, mRef);
    }
    for (auto iter = pagPlayerNapi_.begin(); iter != pagPlayerNapi_.end(); ++iter) {
        if (iter->second != nullptr) {
            delete iter->second;
            iter->second = nullptr;
        }
    }
    pagPlayerNapi_.clear();
}

PAGPlayer::PAGPlayer(napi_env pEnv, std::string &id)
{
    mEnv = pEnv;
    pagPlayerNapiProxy_ = new PagPlayerProxy();
}

PAGPlayer::PAGPlayer(napi_env pEnv, napi_ref pRef)
{
    mEnv = pEnv;
    mRef = pRef;
}

PAGPlayer *PAGPlayer::getInstance(napi_env pEnv, std::string &id)
{
    if (pagPlayerNapi_.find(id) == pagPlayerNapi_.end()) {
        PAGPlayer *instance = new PAGPlayer(pEnv, id);
        pagPlayerNapi_[id] = instance;
        return instance;
    } else {
        return pagPlayerNapi_[id];
    }
}

PAGPlayer *PAGPlayer::GetNapiPlayer(napi_env env, napi_callback_info info)
{
    napi_value thisVar = nullptr;
    napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
    PAGPlayer *pagPlayer = nullptr;
    napi_unwrap(env, thisVar, reinterpret_cast<void **>(&pagPlayer));
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "INIT", "PAGPlayer::PagInit pagPlayer = %{public}p", pagPlayer);
    return pagPlayer;
}

napi_value PAGPlayer::PagInit(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->PagInit(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetSurface(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetSurface(env, info);
    return nullptr;
}

std::string PAGPlayer::GetCurrentXCompentId(napi_env env, napi_callback_info info)
{
    OH_LOG_Print(LOG_APP, LOG_INFO, LOG_PRINT_DOMAIN, "PAGPlayer", "GetCurrentXCompentId");
    size_t argc = PARAM_COUNT_1;
    napi_value args[INDEX_1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    char diStr[1024] = {0};
    size_t charLen = 0;
    napi_get_value_string_utf8(env, args[0], diStr, STR_DEFAULT_SIZE, &charLen);
    std::string idCompent = diStr;
    return idCompent;
}

napi_value PAGPlayer::Prepare(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->Prepare(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetComposition(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetComposition(env, info);
    return nullptr;
}

napi_value PAGPlayer::Duration(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->Duration(env, info);
    return result;
}

napi_value PAGPlayer::CurrentFrame(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->CurrentFrame(env, info);
    return result;
}

napi_value PAGPlayer::GetProgress(napi_env env, napi_callback_info info)
{
    return GetNapiPlayer(env, info)->pagPlayerNapiProxy_->GetProgress(env, info);
}

void PAGPlayer::Destructor(napi_env env, void *nativeObject, void *finalize)
{
    PAGPlayer *pagPlayer = reinterpret_cast<PAGPlayer *>(nativeObject);
    pagPlayer->PAGPlayer::~PAGPlayer();
}

napi_value PAGPlayer::JsPlayerConstructor(napi_env env, napi_callback_info info)
{
    napi_value undefineVar = nullptr;
    napi_value thisVar = nullptr;
    napi_get_undefined(env, &undefineVar);

    if (napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr) == napi_ok && thisVar != nullptr) {
        // 创建PAGPlayer 实例
        PAGPlayer *reference = new PAGPlayer(env);
        // 绑定实例类创建PAGPlayer到导出的对象result
        if (napi_wrap(env, thisVar, reinterpret_cast<void *>(reference), PAGPlayer::Destructor,
            nullptr, &(reference->mRef)) == napi_ok) {
            return thisVar;
        }
        return thisVar;
    }
    return undefineVar;
}

napi_value PAGPlayer::AddPlayerListener(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->AddPlayerListener(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetRepeatCount(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetRepeatCount(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetProgress(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetProgress(env, info);
    return nullptr;
}

napi_value PAGPlayer::Pause(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->Pause(env, info);
    return nullptr;
}

napi_value PAGPlayer::Resume(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->Resume(env, info);

    return nullptr;
}

napi_value PAGPlayer::Stop(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->Stop(env, info);
    return nullptr;
}

napi_value PAGPlayer::GetState(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->GetState(env, info);
    return result;
}

napi_value PAGPlayer::SetScaleMode(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetScaleMode(env, info);
    return nullptr;
}

napi_value PAGPlayer::ScaleMode(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->ScaleMode(env, info);
    return result;
}

napi_value PAGPlayer::NativeSetMatrix(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->NativeSetMatrix(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetCacheEnabled(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetCacheEnabled(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetCacheScale(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetCacheScale(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetMaxFrameRate(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetMaxFrameRate(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetUseDiskCache(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetUseDiskCache(env, info);
    return nullptr;
}

napi_value PAGPlayer::SetVideoEnabled(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->SetVideoEnabled(env, info);
    return nullptr;
}

napi_value PAGPlayer::UseDiskCache(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->UseDiskCache(env, info);
    return result;
}

napi_value PAGPlayer::VideoEnabled(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->VideoEnabled(env, info);
    return result;
}

napi_value PAGPlayer::MaxFrameRate(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->MaxFrameRate(env, info);
    return result;
}

napi_value PAGPlayer::CacheEnabled(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->CacheEnabled(env, info);
    return result;
}

napi_value PAGPlayer::CacheScale(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->CacheScale(env, info);
    return result;
}

napi_value PAGPlayer::GetComposition(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->GetComposition(env, info);
    return result;
}

napi_value PAGPlayer::GetLayersUnderPoint(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->GetLayersUnderPoint(env, info);
    return result;
}

napi_value PAGPlayer::FlushAndFenceSync(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->FlushAndFenceSync(env, info);
    return result;
}

napi_value PAGPlayer::RegisterRepeatCountCallback(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->RegisterRepeatCountCallback(env, info);
    return result;
}

napi_value PAGPlayer::RegisterCurrentFrameCallback(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->RegisterCurrentFrameCallback(env, info);
    return result;
}

napi_value PAGPlayer::RemovePlayStateListener(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->RemovePlayStateListener(env, info);
    return result;
}

napi_value PAGPlayer::RemoveRepeatCountListener(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->RemoveRepeatCountListener(env, info);
    return result;
}

napi_value PAGPlayer::RemoveCurrentFrameListener(napi_env env, napi_callback_info info)
{
    napi_value result = GetNapiPlayer(env, info)->pagPlayerNapiProxy_->RemoveCurrentFrameListener(env, info);
    return result;
}

napi_value PAGPlayer::FreeCache(napi_env env, napi_callback_info info)
{
    GetNapiPlayer(env, info)->pagPlayerNapiProxy_->FreeCache(env, info);
    return nullptr;
}
} // namespace NativeXComponentSample